#include<bits/stdc++.h> 
#define INF 0x3f3f3f3f
using namespace std;
//  加油站需要被建在站台与其余房子之间的最小距离要尽可能大的这样一个地方，但是需要保证所
//	有房子都在其能服务的范围。现在给你一张城市地图和几个加油站的候选地点，你应该给出最佳
//	建议。如果有一个以上的解决方案，请输出与所有房屋的平均距离最小的那个。如果这样的解决
//	方案仍然不是唯一的，则输出索引数最小的那个。
//1.每个输入都包括一个测试用例，对于每个测试用例，第一行包括4个正整数：N≤1000，表示总的
//	房子数。M≤10，表示待选的加油站数。K≤10000，表示房子和加油站之间路的数量。Ds，加油站
//	最大能服务到的范围。设所有的房子编号为1~N，然后所有的待定地点编号为G1~GM
//2.然后跟着K行，每行的格式为P1 P2 Dist。其中P1 P2表示一条路的两端，可能是房子也可能是加
//	油站。然后Dist是路的长度。
//3.对于每个测试用例，输出最佳位置。下一行，输出它和其他房子之间的最小距离以及平均距离
//4.测试用例1的3.3有点问题，最后加上0.05去四舍五入的话，测试用例过得去，但是测试点4会寄
struct Gas{
	float min_dis = INF;
	float ave = 0;
	bool ok = true;
};
long long roads[1020][1020];
bool visited[1020];
long long diss[1020][1020];
long long dist[1020][1020];
Gas gas[15];
vector<long long> gasvec;
vector<long long> posvec;
long long N,M,K,Ds,from,to;
void init(){
	for(long long i = 0;i<1020;i++){
		for(long long j = 0;j<1020;j++){
			dist[i][j] = diss[i][j];
		}
	}
}
void dijkstra(){
	for(long long a=0;a<M;a++){
		fill(visited, visited+1020, false);
		init();
		from = gasvec[a];
		to = gasvec[a];
		dist[from][to] = 0;
		visited[from] = true;
		while(true){
			long long m_i = -1;
			long long m_d = INF;
			for(long long i = 0;i<N;i++){
				to = posvec[i];
				if(visited[to]==false && dist[from][to]<m_d){
					m_i = i;
					m_d = dist[from][to];
				}
			}
			if(m_i==-1) break;
			m_i = posvec[m_i];
			visited[m_i] = true;
			for(long long i = 0;i<N;i++){
				to = posvec[i];
				if(visited[to]==false && roads[m_i][to] != INF){
					if(dist[from][m_i] + roads[m_i][to] < dist[from][to]){
						dist[from][to] = dist[from][m_i] + roads[m_i][to];
					}
				}
			}
		}
		to = from - 1001;
		for(long long i = 1;i<=N-M;i++){
			if(dist[from][i]!=INF){
				if(dist[from][i] > Ds){
					gas[to].ok = false;
					break;
				}
				if(gas[to].min_dis>dist[from][i]) gas[to].min_dis = dist[from][i];
				gas[to].ave += dist[from][i];
			}
		}
		if(gas[to].ok) gas[to].ave /= (N-M) * 1.0;
	}
}
int main(){
	cin>>N>>M>>K>>Ds;
	fill(roads[0], roads[0]+1020*1020, INF);
	fill(diss[0], diss[0]+1020*1020, INF);
	for(long long i = 0;i<K;i++){
		char s[10];
		long long p1, p2, di;
		scanf("%s", s);
		if(s[0]=='G'){
			sscanf(s+1, "%lld", &p1);
			p1 += 1001;
		}
		else{
			sscanf(s, "%lld", &p1);
		} 
		scanf("%s", s);
		if(s[0]=='G'){
			sscanf(s+1, "%lld", &p2);
			p2 += 1001;
		}
		else{
			sscanf(s, "%lld", &p2);
		}
		scanf("%lld", &di);
		roads[p1][p2] = roads[p2][p1] = di;
		diss[p1][p2] = diss[p2][p1] = di;
	}
	for(int i = 0;i<N;i++) posvec.push_back(i+1);
	for(int i = 0;i<M;i++){
		posvec.push_back(i+1002);
		gasvec.push_back(i+1002);
	}
	N += M;
	dijkstra();
	long long min_id = -1;
	for(long long i = 1;i<=M;i++){
		if(gas[i].ok){
			if(min_id == -1 || gas[i].min_dis>gas[min_id].min_dis) min_id = i;
			else if(gas[i].min_dis==gas[min_id].min_dis){
				if(gas[i].ave<gas[min_id].ave) min_id = i;
			}
		}
	}
	if(min_id == -1) cout<<"No Solution"<<endl;
	else{
		printf("G%lld\n%.1f %.1f", min_id, gas[min_id].min_dis, gas[min_id].ave);
	}
	return 0;
}